The increasing complexity of software programs has led to the development of a variety of tools to aid programmers and administrators in understanding the structure and functionality of their programs. Examples of these program analysis tools include debuggers, runtime execution visualizers, development environments and software quality tools. A debugger is a program that interactively traces the logic flow of a program and the contents of memory elements to locate, analyze, and correct bugs in another computer program. Runtime execution tools like profilers use processes like sampling or direct instrumentation to obtain a variety of runtime information, such as heavy memory allocation sites, CPU usage hot-spots, unnecessary object retention, and monitor contention, for a comprehensive performance analysis. A typical integrated development environment (IDE) includes a software application which provides software components to quickly prototype a new application.
A key problem with program analysis tools is how to present complex information about a program to an end user. While program understanding tools are valuable to software developers, testers and administrators in providing insights into the inner workings of what can be complex applications, current approaches for communicating this information are incomplete, often leaving the end-user an with insufficient understanding of the program.
In general, the current approaches to program analysis roughly fall into two groups: (1) the display of temporal flows of information through the program; and (2) the display of containment information, e.g., what objects contain or reference other objects. The most common method to display temporal flows is the sequential execution of events which occur from some start point to some end point. This type of explanation typically focuses on the call stack (i.e., which methods call what other methods). Containment information is typically presented in the form of object reference hierarchies (i.e., which objects refer to what other objects). FIGS. 3A and 3B illustrate one such approach via a textual (FIG. 3A) and graphical (FIG. 3B) object containment hierarchy for the illustrated program of FIG. 2.
For most program analysis processes, the information provided by just one of these two groups of hierarchical representations is of limited value. For example, when debugging a program by tracing through program statements, the user often finds that the program has entered an unexpected state, whether by a variable taking on an unexpected value or by a program executing code that should not have been reached. The chain of events causing the unexpected behavior may be difficult to uncover even with a slow, careful stepping through the program. In such a case, the user needs to resolve how the program arrived at a particular program statement or how a particular variable took on an unexpected value.
Similarly, when starting with object containment displays like FIGS. 3A and 3B, it becomes quickly apparent that certain key program events are missing from the display. Even in the case of the simple program of FIG. 2, these displays fail to show information that the D stored in A was created at a different program point than the D stored in C. For larger (more realistic) applications other information may also be important, such as how particular D got stored into this particular A from program entry points. Again, the object containment representation fails to give the user and adequate understanding of the program.
Thus, there is a need for a better understanding and presentation of information about the different hierarchies representing a program.